package com.newx.test.open.tcp1;

import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @Classname MCUClient
 * @Description TODO 单片机客户端代码（Java客户端）
 * @Date 2025/1/7 15:53
 * @Created by yxl
 */
public class MCUClient {

    public static final int BUFFER_SIZE = 1; // 每个数据包的最大大小

    public static void main(String[] args) {
        String host = "127.0.0.1"; // 服务端IP地址
        int port = 5000; // 服务端监听的TCP端口

        try (Socket socket = new Socket(host, port)) {
            DataInputStream inStream = new DataInputStream(socket.getInputStream());
            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);

            // 发送初始消息给服务端
            out.println("Request file");
            System.out.println("请求文件...");

            // 接收文件并保存到本地
            receiveFile(inStream, out, "F:\\Desktop\\received_example.txt");

        } catch (UnknownHostException e) {
            System.err.println("未知主机: " + e.getMessage());
        } catch (IOException e) {
            System.err.println("IO异常: " + e.getMessage());
        }
    }

    private static void receiveFile(DataInputStream inStream, PrintWriter out, String savePath) throws IOException {
        FileOutputStream fos = new FileOutputStream(savePath);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        // 接收文件名和文件大小
        String fileName = inStream.readUTF();
        long fileSize = inStream.readLong();
        System.out.println("开始接收文件: " + fileName + ", 大小: " + fileSize + " 字节");

        byte[] buffer = new byte[BUFFER_SIZE];
        int expectedPacketNumber = 0;

        // 接收文件内容，分包处理
        while (expectedPacketNumber >= 0) {
            int packetNumber = inStream.readInt(); // 数据包序号
            int bytesRead = inStream.readInt();    // 数据长度

            if (packetNumber != expectedPacketNumber) {
                System.out.println("丢弃错误的数据包 " + packetNumber);
                out.println("NACK " + packetNumber);
                continue;
            }

            // 读取数据包内容
            inStream.readFully(buffer, 0, bytesRead);
            bos.write(buffer, 0, bytesRead);
            bos.flush();

            // 发送确认
            out.println("ACK " + expectedPacketNumber);
            System.out.println("收到并确认数据包 " + expectedPacketNumber);

            expectedPacketNumber++;

            // 如果所有数据包都已接收完毕
            if (fos.getChannel().position() >= fileSize) {
                expectedPacketNumber = -1;
            }
        }

        bos.close();
        fos.close();
        System.out.println("文件接收完成并保存为: " + savePath);
    }
}
